#include "core.h"
#include "xMsgHandler.h"
#include "PacketProcessor.h"
#include "ComputureMgr.h"
#include "Protocal/Common.pb.h"
#include "AsioTcpLink.h"
#include "AsioTcpLinkClient.h"
#include "GlobalConfig.h"
#include "ServerCore.h"
#include "Misc.h"
#include "LogMgr.h"

CMsgHandler::CMsgHandler()
{
	Reg();
}

CMsgHandler::~CMsgHandler()
{

}

void CMsgHandler::Reg()
{
	CPacketProcesser* processer = CPacketProcesser::getInstance();
	if (processer)
	{
		processer->RegCB(MYTH::CMD_Srv_New, boost::BOOST_BIND(&CMsgHandler::OnNewClientLinkConnected, this, _1));
		processer->RegCB(MYTH::CMD_Srv_Reg, boost::BOOST_BIND(&CMsgHandler::OnSrvReg, this, _1));
		processer->RegCB(MYTH::CMD_Srv_Reg_r, boost::BOOST_BIND(&CMsgHandler::OnSrvList, this, _1));
		processer->RegCB(MYTH::CMD_Obj_Del, boost::BOOST_BIND(&CMsgHandler::OnUnbing, this, _1));
	}
}

void CMsgHandler::OnUnbing(xMSG& msg)
{
	MYTH::ObjDleParameter parameter;
	if (parameter.ParseFromArray(msg.getParameterData(), msg.getParameterSize()))
	{
		xObjBase* pObj = xObjBase::getObj(parameter.bind_guid());
		if (pObj)
		{
			pObj->onUnBind();
		}
	}
}

void CMsgHandler::OnNewClientLinkConnected(xMSG& msg)
{
	net_obj_ptr pC = xNetObjBase::getNetObj(msg.call_guid);
	CAsioTcpClient* pClient = dynamic_cast<CAsioTcpClient*>(pC.get());
	if (pClient)
	{
		SendLocalReg(pC);
	}
}

void CMsgHandler::OnSrvReg(xMSG& msg)
{
	net_obj_ptr pC = xNetObjBase::getNetObj(msg.call_guid);
	CAsioTcpLink* pClient = dynamic_cast<CAsioTcpLink*>(pC.get());
	if (pClient)
	{
		CComputureMgr* pCMgr = CComputureMgr::getInstance();
		CServerCore* pCore = CServerCore::getInstance();

		MYTH::SrvReg regInfo;
		if(regInfo.ParseFromArray(msg.getParameterData(), msg.getParameterSize()))
		{
			pClient->setReoteNetType(static_cast<ENetDef::_eNet>(regInfo.local_type()));
		
			if (pClient->getLocalNetType() == ENetDef::NET_CENTER)
			{
				MYTH::SrvReg_R r;
				pCMgr->GetAllSrvs(r);
				xMSG rl(MYTH::CMD_Srv_Reg_r, &r);
				pCore->SendMsg2Net(msg.call_guid, rl);

				MYTH::SrvReg_R r2other;
				MYTH::Srv* pSrv = r2other.add_srvlist();
				pSrv->set_srv_index(regInfo.srv_index());
				pSrv->set_srv_ip_port(regInfo.srv_ip_port());
				pSrv->set_srv_type(regInfo.local_type());
				xMSG rlo(MYTH::CMD_Srv_Reg_r, &r2other);
				pCMgr->SendMsg2AllServer(rlo);
			}
		
			CComputureMgr::getInstance()->AddServer(pClient, &regInfo);

			if (pClient->getEntityType() == CGuidMgr::ENTITY_LINKS)
			{
				SendLocalReg(pC);
			}
		}
	}
}

void CMsgHandler::OnSrvList(xMSG& msg)
{
	net_obj_ptr pC = xNetObjBase::getNetObj(msg.call_guid);
	CAsioTcpLink* pLink = dynamic_cast<CAsioTcpLink*>(pC.get());
	if (pLink)
	{
		CComputureMgr* pCMgr = CComputureMgr::getInstance();
		CServerCore* pCore = CServerCore::getInstance();
		CCfgNet* cfg_net = CClobalConfigMgr::getInstance()->mpCfgNet;

		MYTH::SrvReg_R r;
		if(r.ParseFromArray(msg.getParameterData(), msg.getParameterSize()))
		{
			for (int i = 0; i < r.srvlist_size(); ++i)
			{
				const MYTH::Srv& sSrv = r.srvlist(i);
				itemHMapTcpClientLocal itemTcpClientlocal = cfg_net->mpCurServer->tcp_client_locals.begin();
				for ( ; itemTcpClientlocal != cfg_net->mpCurServer->tcp_client_locals.end(); itemTcpClientlocal++ )
				{
					if(itemTcpClientlocal->second.remote_card==sSrv.srv_type())
					{
						if (pCMgr->getServer(sSrv.srv_ip_port()) == NULL)
						{
							std::string ip; 
							U16 port;
							CMisc::getIpPortFromStr(ip, port, sSrv.srv_ip_port());
							CServerCore::getInstance()->newTcpClient(static_cast<ENetDef::_eNet>(sSrv.srv_type()), ip, port);
						}
					}
				}
			}
		}
	}
}

void CMsgHandler::SendLocalReg(net_obj_ptr link)
{
	net_link_ptr link_ptr = boost::dynamic_pointer_cast<CAsioTcpLink>(link);
	if (link_ptr.get())
	{
		CCfgNet* cfg_net = CClobalConfigMgr::getInstance()->mpCfgNet;
		itemHMapTcpServer index = cfg_net->mpCurServer->tcp_servers.begin();
		for ( ; index != cfg_net->mpCurServer->tcp_servers.end(); index++ )
		{
			if ( index->second.local_card == cfg_net->mpCurServer->local_card )
			{
				MYTH::SrvReg reg;
				reg.set_remote_type(link_ptr->getRemoteNetType());
				reg.set_local_type(link_ptr->getLocalNetType());//index->second.local_card
				reg.set_srv_index(CClobalConfigMgr::getInstance()->mpCfgBase->mSrvIndex);
				std::string ip_port = CMisc::getIpPort(index->second.local_ip, index->second.local_port);
				reg.set_srv_ip_port(ip_port);

				xMSG r(MYTH::CMD_Srv_Reg, &reg);
				CServerCore::getInstance()->SendMsg2Net(link_ptr->getGuid(), r);
				GAMELOGER->debug("CRegComputer %d %s:%d %d to %d %s",
					index->second.local_card,index->second.local_ip.c_str(),index->second.local_port,
					CClobalConfigMgr::getInstance()->mpCfgBase->mSrvIndex,
					link_ptr->getRemoteNetType(), link_ptr->getRemoteIPPort().c_str());

				break;
			}
		}
	}
}